package org.dsapr.codegen.model;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.dsapr.codegen.common.*;

import javax.lang.model.element.TypeElement;
import java.util.Optional;

@Data
@NoArgsConstructor
public class NameContext {
    public final static String CONVERTER_NAME = "%sConverter";
    public final static String CONTROLLER_NAME = "%sController";
    public final static String SERVICE_NAME = "%sService";
    public final static String I_SERVICE_NAME = "I%sService";
    public final static String REPOSITORY_NAME = "%sMapper";

    private String className;
    private String qualifiedName;
    private String entityPackageName;
    private String converterName;
    private String voClassName;
    private String voPackageName;
    private String controllerClassName;
    private String serviceClassName;
    private String iServiceClassName;
    private String repositoryClassName;
    private String converterPackageName;
    private String controllerPackageName;
    private String iServicePackageName;
    private String repositoryPackageName;

    private Method[] controllerMethod;

    public static NameContextBuilder builder() {
        return new NameContextBuilder();
    }

    public String getControllerFullyQualifiedName() {
        if (controllerPackageName == null || controllerClassName == null) {
            return "";
        }
        return controllerPackageName.concat(".").concat(controllerClassName);
    }

    public static class NameContextBuilder {
        public NameContext build(TypeElement t) {
            NameContext nameContext = new NameContext();
            String className = t.getSimpleName().toString();
            nameContext.setQualifiedName(t.getQualifiedName().toString());
            nameContext.setEntityPackageName(t.getQualifiedName().toString().replace("." + className, ""));
            if (className != null) {
                nameContext.setClassName(className);
                nameContext.setVoClassName(String.format("%sVo", className));
                nameContext.setConverterName(String.format(CONVERTER_NAME, className));
                nameContext.setControllerClassName(String.format(CONTROLLER_NAME, className));
                nameContext.setServiceClassName(String.format(SERVICE_NAME, className));
                nameContext.setIServiceClassName(String.format(I_SERVICE_NAME, className));
                nameContext.setRepositoryClassName(String.format(REPOSITORY_NAME, className));
            }

            AutoGenerateController genControllerAnnotation = t.getAnnotation(AutoGenerateController.class);
            Optional.ofNullable(genControllerAnnotation)
                    .map(AutoGenerateController::packageName)
                    .ifPresent(nameContext::setControllerPackageName);

            Optional.ofNullable(genControllerAnnotation)
                    .map(AutoGenerateController::method)
                    .ifPresent(nameContext::setControllerMethod);

            AutoGenerateVo genVoAnnotation = t.getAnnotation(AutoGenerateVo.class);
            Optional.ofNullable(genVoAnnotation)
                    .map(AutoGenerateVo::packageName)
                    .ifPresent(nameContext::setVoPackageName);

            AutoGenerateRepository genRepoAnnotation = t.getAnnotation(AutoGenerateRepository.class);
            Optional.ofNullable(genRepoAnnotation)
                    .map(AutoGenerateRepository::packageName)
                    .ifPresent(nameContext::setRepositoryPackageName);

            AutoGenerateIService genIServiceAnnotation = t.getAnnotation(AutoGenerateIService.class);
            Optional.ofNullable(genIServiceAnnotation)
                    .map(AutoGenerateIService::packageName)
                    .ifPresent(nameContext::setIServicePackageName);

            AutoGenerateConverter genConverterAnnotation = t.getAnnotation(AutoGenerateConverter.class);
            Optional.ofNullable(genConverterAnnotation)
                    .map(AutoGenerateConverter::packageName)
                    .ifPresent(nameContext::setConverterPackageName);

            return nameContext;
        }
    }

}
